package com.openx.cloud.server.autoconfigure.feign;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.openx.cloud.server.autoconfigure.interceptor.FeignRequestInterceptor;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import feign.form.spring.SpringFormEncoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Map;

/**
 * Feign自动配置.
 *
 * @author liuyadu
 */
@Slf4j
@Configuration
public class FeignAutoConfiguration {

    @Bean
    public Encoder springFormEncoder(ObjectMapper objectMapper) {
        Encoder encoder = new SpringMultipartEncoder(new SpringEncoder(new ObjectFactory<HttpMessageConverters>() {
            @Override
            public HttpMessageConverters getObject() throws BeansException {
                MappingJackson2HttpMessageConverter httpMessageConverter = new MappingJackson2HttpMessageConverter();
                httpMessageConverter.setObjectMapper(objectMapper);
                return new HttpMessageConverters(httpMessageConverter);
            }
        }));
        log.info("FeignSpringFormEncoder [{}]", encoder);
        return encoder;
    }

    @Bean
    public ErrorDecoder feignErrorDecoder(ObjectMapper objectMapper) {
        ErrorDecoder errorDecoder = new FeignErrorDecoder(objectMapper);
        log.info("FeignErrorDecoder [{}]", errorDecoder);
        return errorDecoder;
    }

    @Bean
    @ConditionalOnMissingBean(FeignRequestInterceptor.class)
    public RequestInterceptor feignRequestInterceptor() {
        FeignRequestInterceptor interceptor = new FeignRequestInterceptor();
        log.info("FeignRequestInterceptor [{}]", interceptor);
        return interceptor;
    }

    /**
     * 多文件上传拓展
     */
    public class SpringMultipartEncoder extends SpringFormEncoder {
        public SpringMultipartEncoder() {
            super();
        }

        public SpringMultipartEncoder(Encoder delegate) {
            super(delegate);
        }

        @Override
        public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
            // 单MultipartFile判断
            if (bodyType.equals(MultipartFile.class)) {
                MultipartFile file = (MultipartFile) object;
                Map data = Collections.singletonMap(file.getName(), object);
                super.encode(data, MAP_STRING_WILDCARD, template);
                return;
            } else if (bodyType.equals(MultipartFile[].class)) {
                // MultipartFile数组处理
                MultipartFile[] file = (MultipartFile[]) object;
                if (file != null) {
                    Map data = Collections.singletonMap(file.length == 0 ? "" : file[0].getName(), object);
                    super.encode(data, MAP_STRING_WILDCARD, template);
                    return;
                }
            }
            // 其他类型调用父类默认处理方法
            super.encode(object, bodyType, template);
        }
    }
}
